package com.pirestupppai.imagetool.copytool;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

import com.pirestupppai.common.Constant;
import com.pirestupppai.utils.Utils;

import java.util.ArrayList;
import java.util.List;

/**
 * 仿制图章view
 */

public class CopyView extends View {
    /**
     *   根据原始Bitmap创建mTranslateBitmap，根据mTranslateBitmap初始化mCanvas，然后将原始Bitmap和仿制的圆形区域（考虑图片缩放比例）绘制到mCanvas
     *   得到mTranslateBitmap（包含原始Bitmap和仿制区域），显示时，将mTranslateBitmap根据缩放matrix绘制到canvas上。
     *   预览时，首先获取复制区域的clipBitmap，然后将clipBitmap按照缩放比例得到transClipBitmap，绘制到画布上。
     *   每次mCanvas需要清空
     */
    private Context mContext;
    private int surplusHeight;              // 当前屏幕剩余高度
    private float scaleRate;                // 图片缩放比例
    private Matrix mBackgroundMatrix;       // 图片缩放matrix
    private Bitmap mBackgroundBitmap;       // 原始Bitmap

    private Paint mCirclePaint;
    private int mCircleRadius = 100;  // 圆形半径

    private float radiusMarginLeft;      // 圆心距离父控件左边的距离
    private float radiusMarginTop;       // 圆心距离父控件上边的距离

    private float preMarginLeft;              // 拖动圆形前，距离父控件左边的距离
    private float preMarginTop;               // 拖动圆形前，距离父控件上边的距离

    private float mCopyLeft = radiusMarginLeft;                 // 点击复制时，距离父控件左边的距离
    private float mCopyTop = radiusMarginTop;                   // 点击复制时，距离父控件上边的距离

    private float mPasterLeft;                     //  点击粘帖时，距离父控件左边的距离
    private float mPasterTop;                      //  点击粘帖时，距离父控件上边的距离

    private boolean mIsMoveStatus;            // 点击的区域是否在圆形内，如果在，则为可以拖动状态

    private final int NORMAL = 0;                // 未复制状态
    private final int COPY_STATUS = 1;           // 已复制状态
    private int mCurrentStatus = NORMAL;            // 当前仿制的状态
    private List<CustomCopyCircle> mCopyList;       // 当前已经添加的仿制bitmap

    private Canvas mCanvas;
    private Bitmap mTranslateBitmap;        // 绘制原始Bitmap和仿制区域后的Bitmap

    private Bitmap clipBitmap;        // 用于预览复制的Bitmap
    private Bitmap transClipBitmap;   // 用于保存复制Bitmap根据比例缩放后的Bitmap
    private Canvas mClipCanvas;       // 用于根据缩放比例转换Bitmap

    private Paint mClearPaint;        // 用于清屏

    public CopyView(Context context) {
        this(context, null);
        this.mContext = context;
        init();
    }

    public CopyView(Context context, AttributeSet attributeSet) {
        super(context, attributeSet);
        this.mContext = context;
        init();
    }

    private void init() {
        surplusHeight = Constant.HEIGHT_OF_SCREEN - Constant.HEIGHT_OF_STATUSBAR
                - Utils.dpToPx(mContext, 64) - Utils.dpToPx(mContext, 85);

        mCirclePaint = new Paint();
        mCirclePaint.setStyle(Paint.Style.FILL);
        mCirclePaint.setAntiAlias(true);
        mCirclePaint.setColor(Color.parseColor("#3F000000"));

        mCopyList = new ArrayList<>();

        mClearPaint = new Paint();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        mBackgroundMatrix = new Matrix();
        if (mBackgroundBitmap != null) {
            float surplusRate = (float) Constant.WIDTH_OF_SCREEN / (float) surplusHeight;
            float pictureRate = (float) mBackgroundBitmap.getWidth() / (float) mBackgroundBitmap.getHeight();
            if (pictureRate > surplusRate) {
                scaleRate = (float) Constant.WIDTH_OF_SCREEN / (float) mBackgroundBitmap.getWidth();
                setMeasuredDimension(Constant.WIDTH_OF_SCREEN, Constant.WIDTH_OF_SCREEN * mBackgroundBitmap.getHeight() / mBackgroundBitmap.getWidth());
            } else {
                scaleRate = (float) surplusHeight / (float) mBackgroundBitmap.getHeight();
                setMeasuredDimension(surplusHeight * mBackgroundBitmap.getWidth() / mBackgroundBitmap.getHeight(), surplusHeight);
            }
            mBackgroundMatrix.postScale(scaleRate, scaleRate);
        } else {
            setMeasuredDimension(Constant.WIDTH_OF_SCREEN, surplusHeight);
        }
        radiusMarginLeft = getMeasuredWidth() / 2;
        radiusMarginTop = getMeasuredHeight() / 2;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        // draw背景为白色
        canvas.drawColor(Color.parseColor("#FFFFFF"));

        // 清除mCanvas上的绘制
        mClearPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
        mCanvas.drawPaint(mClearPaint);
        mClearPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));

        mCanvas.drawBitmap(mBackgroundBitmap, 0, 0, null);
        for (int i = 0; i < mCopyList.size(); i++) {
            CustomCopyCircle customCopyCiscle = mCopyList.get(i);
            mCanvas.drawBitmap(customCopyCiscle.bitmap, customCopyCiscle.marginLeft, customCopyCiscle.marginTop, null);
        }
        canvas.drawBitmap(mTranslateBitmap, mBackgroundMatrix, null);

        // 当前为复制或者粘帖状态，将已复制Bitmap预览到移动的圆形区域内
        // 首先拿到复制的Bitmap，然后根据缩放比例放大，最后draw到画布上的指定位置
        if (mCurrentStatus == COPY_STATUS) {
            clipBitmap = Bitmap.createBitmap(mBackgroundBitmap, (int) ((mCopyLeft - mCircleRadius) / scaleRate),
                    (int) ((mCopyTop - mCircleRadius) / scaleRate), (int) (2 * mCircleRadius / scaleRate),
                    (int) (2 * mCircleRadius / scaleRate), null, true);

            transClipBitmap = Bitmap.createBitmap((int) (clipBitmap.getWidth() * scaleRate), (int) (clipBitmap.getHeight() * scaleRate), Bitmap.Config.ARGB_8888);
            mClipCanvas = new Canvas(transClipBitmap);
            mClipCanvas.drawBitmap(clipBitmap, mBackgroundMatrix, null);

            clipBitmap = getCircleBitmap(transClipBitmap);
            canvas.drawBitmap(clipBitmap, radiusMarginLeft - mCircleRadius, radiusMarginTop - mCircleRadius, null);
        }

        // draw 拖动区域
        canvas.drawCircle(radiusMarginLeft, radiusMarginTop, mCircleRadius, mCirclePaint);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction() & MotionEvent.ACTION_MASK) {
            case MotionEvent.ACTION_DOWN:  // 手指压下屏幕
                if (IsTouchInCircle((int) event.getX(), (int) event.getY())) {
                    mIsMoveStatus = true;
                    preMarginLeft = radiusMarginLeft;
                    preMarginTop = radiusMarginTop;
                } else {
                    mIsMoveStatus = false;
                }
                break;
            case MotionEvent.ACTION_MOVE: // 手指在屏幕移动，该事件会不断地触发
                if (mIsMoveStatus) {
                    float curX = event.getX();
                    float curY = event.getY();

                    //  仿制区域，边界判断
                    if (curX < mCircleRadius) {
                        curX = mCircleRadius;
                    }
                    if((curX + mCircleRadius) > getWidth()) {
                        curX = getWidth() - mCircleRadius;
                    }
                    if(curY < mCircleRadius) {
                        curY = mCircleRadius;
                    }
                    if((curY + mCircleRadius) > getHeight()) {
                        curY = getHeight() - mCircleRadius;
                    }

                    float dx = curX - preMarginLeft;
                    float dy = curY - preMarginTop;

                    radiusMarginLeft += dx;
                    radiusMarginTop += dy;

                    preMarginLeft = curX;
                    preMarginTop = curY;

                    invalidate();
                }
                break;
            case MotionEvent.ACTION_UP:
                mIsMoveStatus = false;
                break;
        }
        return true;
    }

    /**
     *  判断点击区域是否在圆形内，触摸点距圆心小于半径
     */
    private boolean IsTouchInCircle(int touchX, int touchY) {
        float dx = touchX - radiusMarginLeft;
        float dy = touchY - radiusMarginTop;
        float distance = (float) Math.sqrt(dx * dx + dy * dy);

        if (distance > mCircleRadius) {
            return false;
        } else {
            return true;
        }
    }

    /**
     *  复制，记录当前圆形区域的位置
     */
    public void CopyStatus() {
        mCurrentStatus = COPY_STATUS;
        this.mCopyLeft = radiusMarginLeft;
        this.mCopyTop = radiusMarginTop;

        invalidate();
    }

    /**
     *  粘帖，考虑当前BackgroundBitmap的缩放比例
     */
    public void PasterStatus() {
        if (mCurrentStatus == COPY_STATUS) {
            mPasterLeft = radiusMarginLeft - mCircleRadius;
            mPasterTop = radiusMarginTop - mCircleRadius;

            Bitmap clipBitmap = Bitmap.createBitmap(mBackgroundBitmap, (int) ((mCopyLeft - mCircleRadius) / scaleRate),
                    (int) ((mCopyTop - mCircleRadius) / scaleRate), (int) (2 * mCircleRadius / scaleRate),
                    (int) ((2 * mCircleRadius) / scaleRate), null, true);
            clipBitmap = getCircleBitmap(clipBitmap);

            CustomCopyCircle customCopyCircle = new CustomCopyCircle((int) (mCircleRadius / scaleRate), (int) (mPasterLeft / scaleRate),
                    (int) (mPasterTop / scaleRate), clipBitmap);
            mCopyList.add(customCopyCircle);

            invalidate();
        }
    }

    /**
     *  根据矩形获取圆形图片
     */
    public static Bitmap getCircleBitmap(Bitmap bitmap) {
        int x = bitmap.getWidth();
        int y = bitmap.getHeight();
        Bitmap output = Bitmap.createBitmap(x, y, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(output);

        final int color = 0xff424242;
        final Paint paint = new Paint();
        // 根据原来图片大小画一个矩形
        final Rect rect = new Rect(0, 0, x, y);
        paint.setAntiAlias(true);
        paint.setColor(color);
        // 画出一个圆
        canvas.drawCircle(x / 2, x / 2, x / 2 - 5, paint);
        //canvas.translate(-25, -6);
        // 取两层绘制交集,显示上层
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));

        // 将图片画上去
        canvas.drawBitmap(bitmap, rect, rect, paint);
        // 返回Bitmap对象
        return output;
    }

    /**
     * 设置背景Bitmap
     */
    public void setBackgroundBitmap(Bitmap bitmap) {
        this.mBackgroundBitmap = bitmap;
        mTranslateBitmap = Bitmap.createBitmap(mBackgroundBitmap.getWidth(), mBackgroundBitmap.getHeight(), Bitmap.Config.ARGB_8888);
        mCanvas = new Canvas(mTranslateBitmap);
        invalidate();
    }

    /**
     *  获得绘制后的Bitmap
     */
    public Bitmap getmBackgroundBitmap() {
        return mTranslateBitmap;
    }

    /**
     *  设置仿制区域的大小
     */
    public void setCircleSize(int size) {
        mCurrentStatus = NORMAL;
        this.mCircleRadius = size;
        invalidate();

    }
}
